uniform sampler2D tex_depth, tex_norm, tex_motion;
uniform sampler2D tex_shadow_map;
uniform int t_debug;
uniform mat4 invprojmtx, projmtx, modelviewmtx, invmodelviewmtx;

// light data
uniform vec3 light_pos;
uniform int  light_type;

void main (void)
{
	// depth
	float depth = texture2D(tex_depth, gl_TexCoord[0].st).r * 2.0 - 1.0;

	// normal
	vec4 norm = texture2D(tex_norm, gl_TexCoord[0].st);
	norm.xyz = norm.xyz * 2.0 - 1.0;

	// motion + spec buffer
	vec4 motion = texture2D(tex_motion, gl_TexCoord[0].st);
	float mat_shininess = pow(2.0, motion.b * 10.5);
	float mat_specular = motion.a;


	// Viewport position at this pixel in the range -1 to 1.
	vec4 projection_pos = vec4(gl_TexCoord[0].st * 2.0 - 1.0, depth, 1.0);
		
	// Transform by the view-projection inverse.
	vec4 viewport_pos = invprojmtx * projection_pos;
		
	// Divide by w to get the world position.
	vec4 frag_pos = viewport_pos / viewport_pos.w;
	

	// Blinn-Phong calculations
	vec3 eyeVec = -vec3(frag_pos.xyz);
	vec3 lightDir = ((modelviewmtx * vec4(light_pos, 1.0)).xyz + eyeVec);


	vec3 light_color = gl_LightSource[0].ambient.rgb;
	float specular = 0.0;
	float distanceFromLight = 0.0;

	vec3 N = normalize(norm.xyz);
	vec3 L = normalize(lightDir);
	
	float lambertTerm = dot(N,L);
	if(lambertTerm > 0.0)
	{
		if (light_type == 0) // Point light
		{

			light_color += gl_LightSource[0].diffuse.rgb * lambertTerm;
			
			vec3 E = normalize(eyeVec);
			vec3 H = normalize((L + E) / length(L + E));
			specular = mat_specular * pow( max(dot(N, H), 0.0), mat_shininess );


		} else if (light_type == 1) // Spot light
		{

			float spotEffect = dot(normalize(modelviewmtx * vec4(gl_LightSource[0].spotDirection, 0.0)).xyz, -L);

			if (spotEffect > gl_LightSource[0].spotCosCutoff) {

				// Shadow maps
				vec4 light_shadowcoord = gl_TextureMatrix[3] * (invmodelviewmtx * frag_pos);
				vec4 shadowCoordinateWdivide = light_shadowcoord / light_shadowcoord.w;

				// Used to lower moir pattern and self-shadowing
				shadowCoordinateWdivide.z += 0.00001;
				distanceFromLight = texture2D(tex_shadow_map, shadowCoordinateWdivide.st).z;
				float shadow = 1.0;

				if (light_shadowcoord.w > 0.0)
					shadow = distanceFromLight < shadowCoordinateWdivide.z ? 0.3 : 1.0 ;

				// Blinn-Phong
				float dist = length(lightDir);
				spotEffect = pow(spotEffect, gl_LightSource[0].spotExponent);
				float att = spotEffect / (gl_LightSource[0].constantAttenuation +
						gl_LightSource[0].linearAttenuation * dist +
						gl_LightSource[0].quadraticAttenuation * dist * dist);


				light_color += shadow * att * gl_LightSource[0].diffuse.rgb * lambertTerm;

				vec3 E = normalize(eyeVec);
				vec3 H = normalize((L + E) / length(L + E));
				specular = shadow * att * mat_specular * pow( max(dot(N, H), 0.0), mat_shininess );

			}


		} else { // Unknown light type
			light_color = vec3(1.0, 0.2, 0.0);
		}
	}

	
	//gl_FragColor = vec4(depth, depth, depth, 1.0);
	//gl_FragColor = vec4(pos.xyz, 1.0);;
	//gl_FragColor = vec4(norm, 1.0);
	
	//if (t_debug == 1)
	//	gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
	//else
		gl_FragColor = vec4(light_color, specular);//vec4(light_color, 0.5);//vec4(eyeVec.xyz, 1.0);
		//gl_FragColor = vec4(distanceFromLight, distanceFromLight, distanceFromLight, 0.0);
		//gl_FragData[1] = vec4(0.0, 0.0, 0.0, specular);//vec4(light_color, 0.5);//vec4(eyeVec.xyz, 1.0);

	//gl_FragColor = vec4(length(lightDir) * 0.5, 0.0, 0.0, 1.0);

	//gl_FragColor = pos;
	//gl_FragColor = vec4(length(lightDir), 0.0, 0.0, 1.0);
}
